package com.uinnova.product.eam.service.cj.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import com.binary.core.util.BinaryUtils;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.cj.domain.PlanDesignShareRecord;
import com.uinnova.product.eam.model.cj.enums.PlanShareEnum;
import com.uinnova.product.eam.model.cj.enums.PlanSharePermissionEnum;
import com.uinnova.product.eam.model.cj.enums.ShareTypeEnum;
import com.uinnova.product.eam.model.cj.request.ShareRecordRequest;
import com.uinnova.product.eam.model.cj.vo.PlanShareDetailVO;
import com.uinnova.product.eam.model.cj.vo.ShareVO;
import com.uinnova.product.eam.service.EamDiagramRelationSysService;
import com.uinnova.product.eam.service.ShareDiagramSvc;
import com.uinnova.product.eam.service.cj.dao.PlanDesignInstanceDao;
import com.uinnova.product.eam.service.cj.dao.PlanDesignShareRecordDao;
import com.uinnova.product.eam.service.cj.service.PlanDiagramSharedQueryService;
import com.uinnova.project.base.diagram.comm.diagram.ESDiagramShareRecordResult;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uino.util.sys.SysUtil;
import org.elasticsearch.index.query.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 方案视图的分享查询service实现
 *
 * @author zhaoxin
 */
@Service
public class PlanDiagramSharedQueryServiceImpl implements PlanDiagramSharedQueryService {

    @Resource
    private PlanDesignShareRecordDao planDesignShareRecordDao;

    @Resource
    private PlanDesignInstanceDao planDesignInstanceDao;

    @Resource
    private ShareDiagramSvc shareDiagramSvc;

    @Resource
    private EamDiagramRelationSysService eamDiagramRelationSysService;

    /**
     * 查询你分享
     *
     * @param request 参数
     * @return list
     */
    @Override
    public List<ShareVO> queryShare(ShareRecordRequest request) {
        request.setPageSize(3000);
        request.setPageNum(1);
        Boolean queryPlan = request.getQueryPlan();
        Boolean queryDiagram = request.getQueryDiagram();
        List<ESDiagramShareRecordResult> diagramShareList = null;
        List<PlanDesignShareRecord> planShareList = null;

        if (queryDiagram != null && queryDiagram) {
            Page<ESDiagramShareRecordResult> resultPage = shareDiagramSvc.queryShareDirgram(request);
            if (resultPage.getTotalRows() == 0) {
                return Collections.emptyList();
            }
            List<ESDiagram> diagrams =
                    resultPage.getData().stream().map(ESDiagramShareRecordResult::getEsDiagram).collect(Collectors.toList());
            eamDiagramRelationSysService.esDiagramSetRelationProperties(diagrams);
            diagramShareList = resultPage.getData();
        }

        if (queryPlan != null && queryPlan) {
            BoolQueryBuilder query = QueryBuilders.boolQuery();
            query.must(QueryBuilders.termQuery("status", PlanShareEnum.SHARING.getStatus()));
            query.must(QueryBuilders.termQuery("sharedLoginCode.keyword", SysUtil.getCurrentUserInfo().getLoginCode()));
            planShareList = planDesignShareRecordDao.getListByQuery(query);
        }

        return mergeShareRecords(planShareList, diagramShareList, request.getLike());
    }

    /**
     * 查询方案分享详情
     *
     * @param planId 方案Id
     * @return {@link PlanShareDetailVO}
     */
    @Override
    public PlanShareDetailVO queryPlanShareDetail(Long planId) {
        PlanDesignInstance plan = planDesignInstanceDao.getById(planId);

        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("status", PlanShareEnum.SHARING.getStatus()));
        query.must(QueryBuilders.termQuery("planDesignId", planId));
        List<PlanDesignShareRecord> shareList = planDesignShareRecordDao.getListByQuery(query);

        if (BinaryUtils.isEmpty(shareList)) {
            return PlanShareDetailVO.builder()
                    .ownerLoginCode(plan.getCreatorCode())
                    .shareList(Collections.emptyList())
                    .build();
        }

        shareList.sort((a, b) -> (int) (b.getShareTime() - a.getShareTime()));
        int fieldCount = PlanDesignShareRecord.class.getDeclaredFields().length;
        Map<Integer, String> permissionDisplayNameMap =
                Arrays.stream(PlanSharePermissionEnum.values()).collect(Collectors.toMap(PlanSharePermissionEnum::getFlag,
                        PlanSharePermissionEnum::getDisplayName));
        List<Map<String, Object>> list = shareList.stream().map(share -> {
            Map<String, Object> map = MapUtil.newHashMap(fieldCount + 1);
            BeanUtil.copyProperties(share, map);

            Integer flag = share.getPermission();
            String permissionDisplayName = permissionDisplayNameMap.get(flag);
            map.put("permissionDisplayName", permissionDisplayName);
            return map;
        }).collect(Collectors.toList());

        return PlanShareDetailVO.builder()
                .ownerLoginCode(plan.getCreatorCode())
                .shareList(list)
                .build();
    }

    private List<ShareVO> mergeShareRecords(List<PlanDesignShareRecord> planShareList,
                                            List<ESDiagramShareRecordResult> diagramShareList, String like) {

        List<ShareVO> list = new LinkedList<>();

        if (!BinaryUtils.isEmpty(planShareList)) {
            addPlanShare(planShareList, like, list);
        }

        if (!BinaryUtils.isEmpty(diagramShareList)) {
            addDiagramShare(diagramShareList, list);
        }

        if (list.size() > 1) {
            list.sort((a, b) -> (int) (b.getTime() - a.getTime()));
        }

        return list;
    }

    private void addDiagramShare(List<ESDiagramShareRecordResult> diagramShareList, List<ShareVO> list) {
        for (ESDiagramShareRecordResult diagramShare : diagramShareList) {
            ESDiagram esDiagram = diagramShare.getEsDiagram();

            if (esDiagram == null) {
                continue;
            }

            list.add(ShareVO.builder()
                    .shareType(ShareTypeEnum.DIAGRAM)
                    .time(diagramShare.getDiagramModifyTime())
                    .title(esDiagram.getName())
                    .data(diagramShare)
                    .build());
        }
    }

    private List<PlanDesignInstance> getByIds(Collection<Long> ids, String like) {
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        TermsQueryBuilder must = QueryBuilders.termsQuery("id", ids);
        boolQuery.must(must);

        if (!BinaryUtils.isEmpty(like)) {
            boolQuery.must(QueryBuilders.multiMatchQuery(like, "name")
                    .operator(Operator.AND).type(MultiMatchQueryBuilder.Type.PHRASE_PREFIX).lenient(true));
        }

        return planDesignInstanceDao.getListByQuery(boolQuery);
    }

    private void addPlanShare(List<PlanDesignShareRecord> planShareList, String like, List<ShareVO> list) {
        List<Long> planIdList =
                planShareList.stream().map(PlanDesignShareRecord::getPlanDesignId).collect(Collectors.toList());


        List<PlanDesignInstance> planList = getByIds(planIdList, like);
        if (BinaryUtils.isEmpty(planList)) {
            return;
        }

        Map<Long, PlanDesignInstance> planMap =
                planList.stream().collect(Collectors.toMap(PlanDesignInstance::getId, plan -> plan,
                        (k1, k2) -> k1));

        if (BinaryUtils.isEmpty(planMap)) {
            return;
        }

        for (PlanDesignShareRecord planShare : planShareList) {
            PlanDesignInstance plan = planMap.get(planShare.getPlanDesignId());

            if (plan == null) {
                continue;
            }

            list.add(ShareVO.builder()
                    .shareType(ShareTypeEnum.PLAN)
                    .time(planShare.getShareTime())
                    .title(plan.getName())
                    .data(plan)
                    .build());

        }
    }
}
